package com.wyt.cloud.utils.query.duty.handler;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.google.common.collect.Sets;
import com.wyt.cloud.utils.designpatterns.dutychain.IHandler;
import com.wyt.cloud.utils.exception.BusinessException;
import com.wyt.cloud.utils.page.PageRequest;
import com.wyt.cloud.utils.query.ClazzFieldsUtil;
import com.wyt.cloud.utils.query.OrderByDirectionEnum;
import com.wyt.cloud.utils.query.anno.FilterParam;
import com.wyt.cloud.utils.query.duty.QueryTask;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * 防止前后端将不存在的字段作为查询条件，导致sql报错
 *
 * @param <S>
 * @param <T>
 */
@Order(1)
@Component
@Slf4j
public class ValidateQueryParamsHandler<S, T> implements IHandler<QueryTask<S, T>> {
    @Override
    public void execute(QueryTask<S, T> task) {
        if (task.getTClass() == null) {
            return;
        }
        validateParams(new BeanWrapperImpl(task.getEntity()), task.getTClass());
    }

    /**
     * @param sourceBeanWrapper
     * @param targetClazz
     */
    private void validateParams(BeanWrapperImpl sourceBeanWrapper, Class<T> targetClazz) {
        List<Field> sourceFields = ClazzFieldsUtil.getAllFields(sourceBeanWrapper.getRootClass(), PageRequest.class);
        Set<String> sourceFieldsName = Sets.newHashSet();
        for (Field sourceField : sourceFields) {
            if (Modifier.isStatic(sourceField.getModifiers())) {
                continue;
            }
            handleFilterFields(sourceFieldsName, sourceField);
            handleSortFields(sourceFieldsName, sourceField, sourceBeanWrapper);
        }
        List<Field> targetFields = ClazzFieldsUtil.getAllFields(targetClazz);
        List<String> targetFieldsName = targetFields.stream().map(Field::getName).collect(Collectors.toList());
        for (String sourceFieldName : sourceFieldsName) {
            if (!targetFieldsName.contains(sourceFieldName)) {
                log.error("查询条件:{}字段有误，请重新配置入参", sourceFieldName);
                throw new BusinessException("查询条件：" + sourceFieldName + "字段有误，请重新配置入参");
            }
        }
    }


    /**
     * 处理过滤条件字段
     *
     * @param sourceFieldsName
     * @param sourceField
     */
    private static void handleFilterFields(Set<String> sourceFieldsName, Field sourceField) {
        FilterParam filterParam = sourceField.getAnnotation(FilterParam.class);
        if (QueryTask.sortFields.equals(sourceField.getName())) {
            return;
        }
        if (filterParam != null && !filterParam.needMatch()) {
            return;
        }
        if (filterParam != null && StringUtils.isNotBlank(filterParam.matchField())) {
            sourceFieldsName.add(filterParam.matchField());
        } else {
            sourceFieldsName.add(sourceField.getName());
        }
    }

    /**
     * 处理排序条件字段
     *
     * @param sourceFieldsName
     * @param sourceField
     * @param beanWrapper
     * @return
     */
    private static void handleSortFields(Set<String> sourceFieldsName, Field sourceField, BeanWrapperImpl beanWrapper) {
        if (!QueryTask.sortFields.equals(sourceField.getName())) {
            return;
        }
        //添加入参传过来的字段
        Map<String, OrderByDirectionEnum> sortFieldMap = (Map<String, OrderByDirectionEnum>) beanWrapper.getPropertyValue(sourceField.getName());
        if (CollectionUtils.isEmpty(sortFieldMap)) {
            return;
        }
        sortFieldMap.forEach((k, v) -> sourceFieldsName.add(k));
    }

}
